package net.hn.hnms.biz.safety.monitor.company.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import net.hn.hnms.biz.api.mine.RemoteMineInfoService;
import net.hn.hnms.biz.api.mine.model.GasIndicatorVo;
import net.hn.hnms.biz.api.safety.location.model.CompanyAlarmVo;
import net.hn.hnms.biz.api.safety.monitor.model.CompanyNowMonitorVo;
import net.hn.hnms.biz.safety.monitor.domain.SensorAlarmPo;
import net.hn.hnms.biz.safety.monitor.domain.vo.NowSensorAlarmVo;
import net.hn.hnms.biz.safety.monitor.mapper.SensorAlarmMapper;
import net.hn.hnms.sys.common.core.constant.Constants;
import net.hn.hnms.sys.common.core.domain.R;
import net.hn.hnms.sys.common.core.exception.HuaNengException;
import net.hn.hnms.sys.common.core.utils.StringUtils;
import net.hn.hnms.sys.common.redis.domain.SysOrganizationVo;
import net.hn.hnms.sys.common.redis.utils.RedisUtils;
import net.hn.hnms.sys.system.api.domain.SysDictData;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 智呈物联 pan'sx
 * 2022/12/26 14:50
 * 1.0 version
 */
@Service
@RequiredArgsConstructor
public class CompanyMonitorService {
    private final JdbcTemplate monitorJdbcTemplate;
    private final RemoteMineInfoService remoteMineInfoService;

    @Resource
    private SensorAlarmMapper sensorAlarmMapper;

    public CompanyNowMonitorVo nowMonitor(String companyCode) {
        String where="";
        if(StringUtils.isNotBlank(companyCode)){
            where=" and company_code ='"+companyCode+"'";
        }
        CompanyNowMonitorVo vo = new CompanyNowMonitorVo();
        String countSql = "SELECT count(distinct point_code) FROM \"dwd_aqjk_now_sensormonitor\" where 1=1 %s";
        vo.setCount(monitorJdbcTemplate.queryForObject(String.format(countSql,where), Integer.class));
        String ch4Sql = "SELECT count(distinct point_code) FROM \"dwd_aqjk_now_sensormonitor\" where sensor_type='0001' %s";
        vo.setCh4(monitorJdbcTemplate.queryForObject(String.format(ch4Sql,where), Integer.class));
        String ch4AlarmSql = "SELECT COUNT(1) \n" +
                "FROM\n" +
                "	dwd_aqjk_now_sensoralarm_count_stat \n" +
                "WHERE\n" +
                "	sensor_type = '0001' \n" +
                "	AND end_time IS NOT NULL \n" +
                "	AND max_value IS NOT NULL \n" +
                "	AND ( end_time > CURRENT_TIMESTAMP - INTERVAL '10 minutes' OR begin_time > CURRENT_TIMESTAMP - INTERVAL '10 minutes' ) \n" +
                "	AND outlier_type = '001' %s";
        vo.setCh4Alarm(monitorJdbcTemplate.queryForObject(String.format(ch4AlarmSql,where), Integer.class));
        String coSql = "SELECT count(distinct point_code) FROM \"dwd_aqjk_now_sensormonitor\" where sensor_type='0004' %s";
        vo.setCo(monitorJdbcTemplate.queryForObject(String.format(coSql,where), Integer.class));
        String coAlarmSql = "SELECT COUNT(1) \n" +
                "FROM\n" +
                "	dwd_aqjk_now_sensoralarm_count_stat \n" +
                "WHERE\n" +
                "	sensor_type = '0004' \n" +
                "	AND end_time IS NOT NULL \n" +
                "	AND max_value IS NOT NULL \n" +
                "	AND ( end_time > CURRENT_TIMESTAMP - INTERVAL '10 minutes' OR begin_time > CURRENT_TIMESTAMP - INTERVAL '10 minutes' ) \n" +
                "	AND outlier_type = '001' %s ";
        vo.setCoAlarm(monitorJdbcTemplate.queryForObject(String.format(coAlarmSql,where), Integer.class));
        String windSpeedSql = "SELECT count(distinct point_code) FROM \"dwd_aqjk_now_sensormonitor\" where sensor_type='0002' %s";
        vo.setWindSpeed(monitorJdbcTemplate.queryForObject(String.format(windSpeedSql,where), Integer.class));
        String windSpeedAlarmSql = "SELECT COUNT(1) \n" +
                "FROM\n" +
                "	dwd_aqjk_now_sensoralarm_count_stat \n" +
                "WHERE\n" +
                "	sensor_type = '0002' %s \n" +
                "	AND end_time IS NOT NULL \n" +
                "	AND max_value IS NOT NULL \n" +
                "	AND ( end_time > CURRENT_TIMESTAMP - INTERVAL '10 minutes' OR begin_time > CURRENT_TIMESTAMP - INTERVAL '10 minutes' ) ";
        vo.setWindSpeedAlarm(monitorJdbcTemplate.queryForObject(String.format(windSpeedAlarmSql,where), Integer.class));
        String dustSql = "SELECT count(distinct point_code) FROM \"dwd_aqjk_now_sensormonitor\" where sensor_type='0014' %s";
        vo.setDust(monitorJdbcTemplate.queryForObject(String.format(dustSql,where), Integer.class));
        String dustAlarmSql = "SELECT COUNT(1) \n" +
                "FROM\n" +
                "	dwd_aqjk_now_sensoralarm_count_stat \n" +
                "WHERE\n" +
                "	sensor_type = '0014' \n" +
                "	AND end_time IS NOT NULL \n" +
                "	AND max_value IS NOT NULL \n" +
                "	AND ( end_time > CURRENT_TIMESTAMP - INTERVAL '10 minutes' OR begin_time > CURRENT_TIMESTAMP - INTERVAL '10 minutes' ) " +
                "	AND outlier_type = '001' %s";
        vo.setDustAlarm(monitorJdbcTemplate.queryForObject(String.format(dustAlarmSql,where), Integer.class));

        String calibrationSql = "SELECT count(distinct point_code) FROM \"dwd_aqjk_his_sensoralarm\" where data_time>CURRENT_DATE and  outlier_type='007' %s";
        vo.setCalibration(monitorJdbcTemplate.queryForObject(String.format(calibrationSql,where), Integer.class));
        return vo;
    }

    public List<CompanyAlarmVo.Info> todayAlarm(String companyCode) {
        String where="";
        if(StringUtils.isNotBlank(companyCode)){
            where=" and company_code ='"+companyCode+"'";
        }
        String sql = "SELECT * FROM \"dwd_aqjk_now_sensoralarm_count_stat\" where begin_time> CURRENT_DATE %s";
        List<Map<String, Object>> maps = monitorJdbcTemplate.queryForList(String.format(sql,where));
        List<CompanyAlarmVo.Info> infos = new ArrayList<>();
        CompanyAlarmVo vo = new CompanyAlarmVo();
        for (Map<String, Object> map : maps) {
            CompanyAlarmVo.Info info = vo.new Info();
            info.setMineName(Constants.mineCodeName.get(map.get("mine_code")));
            info.setAlarmType(map.get("outlier_type_name") + "");
            info.setBeginTime((Date) map.get("begin_time"));
            info.setCause(map.get("abnormal_cause") + "");
            infos.add(info);
        }
        return infos;
    }

    public List<GasIndicatorVo> score(String[] containOrgs) {
        List<GasIndicatorVo> list = new ArrayList<>();
        for (String org : containOrgs) {
            R<GasIndicatorVo> gasIndicatorVoR = remoteMineInfoService.gasIndicator(org);
            if (gasIndicatorVoR.getCode() == Constants.SUCCESS) {
                GasIndicatorVo data = gasIndicatorVoR.getData();
                list.add(data);
            }
        }
        return list;
    }

    public CompanyNowMonitorVo todayMonitor(String companyCode) {
        String where="";
        if(StringUtils.isNotBlank(companyCode)){
            where=" and company_code ='"+companyCode+"'";
        }
        CompanyNowMonitorVo vo = new CompanyNowMonitorVo();
        String ch4Sql = "select count(1) from aqjk.dwd_aqjk_now_sensormonitor " +
                "where sensor_type ='0001' " +
                "and point_status = '1' and data_time > current_date %s ";
        vo.setCh4(monitorJdbcTemplate.queryForObject(String.format(ch4Sql,where), Integer.class));
        String coSql = "select count(1) from aqjk.dwd_aqjk_now_sensormonitor " +
                "where sensor_type ='0004' " +
                "and point_status = '1' and data_time > current_date %s";
        vo.setCo(monitorJdbcTemplate.queryForObject(String.format(coSql,where), Integer.class));
        return vo;
    }

    /**
     * 根据气体获取今日实时传感器报警
     * @param  companyCode
     * @return
     */
    public List<NowSensorAlarmVo> getTodayNowSensorAlarmByGases(String companyCode, String gasesTypeName) {
        if (StringUtils.isEmpty(companyCode)) {
            throw new HuaNengException(Constants.FAIL, "公司编码不可以为空");
        }
        //获取当前公司的所有煤矿
        SysOrganizationVo sysOrganizationVo = RedisUtils.getCacheObject(Constants.SYS_CODESUB_KEY + companyCode);
        if (sysOrganizationVo == null) {
            throw new HuaNengException(Constants.FAIL, "无法获取当前公司的子煤矿信息，请检查词典"+companyCode);
        }
        //获取安全监控所有测点类型
        List<SysDictData> sysDictData = RedisUtils.getCacheObject(Constants.SYS_DICT_KEY + "aqjk_sensor_type");
        String pointTypeCode = "";
        for (SysDictData sysDictDatum : sysDictData) {
            if (gasesTypeName.equals(sysDictDatum.getDictLabel())) {
                pointTypeCode = sysDictDatum.getDictValue();
                break;
            }
        }
        if (StringUtils.isEmpty(pointTypeCode)) {
            throw new HuaNengException(Constants.FAIL, "安全监控测点类型编码无法从字典中查询，请输入正确的测点类型名称" + gasesTypeName);
        }
        List<NowSensorAlarmVo> voList = new ArrayList<>();

        for (SysOrganizationVo organizationVo : sysOrganizationVo.getSubCodeList()) {
            //遍历当前公司的所有煤矿

            // 获取当前日期
            LocalDate today = LocalDate.now();
            LambdaQueryWrapper<SensorAlarmPo> wrapper = new LambdaQueryWrapper<>();
            //今天的日期
            wrapper.apply("DATE(data_time) = '" + today + "'");
            //当前煤矿编码
            wrapper.eq(SensorAlarmPo::getMineCode, organizationVo.getOrgCode());
            //传感器类型编码
            wrapper.eq(SensorAlarmPo::getSensorType, pointTypeCode);
            List<SensorAlarmPo> sensorAlarmPos = sensorAlarmMapper.selectList(wrapper);
            for (NowSensorAlarmVo nowSensorAlarmVo : sensorAlarmPos.stream().map(t -> {
                NowSensorAlarmVo nowSensorAlarmVo = new NowSensorAlarmVo();
                //测点编码
                nowSensorAlarmVo.setPointCode(t.getPointCode());
                //传感器位置
                nowSensorAlarmVo.setPointLocation(t.getPointLocation());
                //煤矿信息
                nowSensorAlarmVo.setMineCode(t.getMineCode());
                nowSensorAlarmVo.setMineName(organizationVo.getOrgName());
                //报警开始时间
                nowSensorAlarmVo.setBeginTime(t.getBeginTime());
                //报警结束时间
                nowSensorAlarmVo.setEndTime(t.getEndTime());
                //异常期间最大值
                nowSensorAlarmVo.setMaxValue(t.getMaxValue());
                //异常原因
                nowSensorAlarmVo.setAbnormalCause(t.getAbnormalCause());
                //处理措施
                nowSensorAlarmVo.setMeasure(t.getMeasure());
                //报警时长
                Duration between = Duration.between(t.getBeginTime().toInstant(), t.getEndTime().toInstant());
                nowSensorAlarmVo.setDuration(minutConversion(new BigDecimal(between.toMinutes())));
                return nowSensorAlarmVo;

            }).collect(Collectors.toList())) {
                //获取的煤矿数据汇总
                voList.add(nowSensorAlarmVo);
            }
        }
        return voList;

    }
    /**
     *  传递一个数值类型 分钟数
     * @param minutes
     * @return 返回 **天**时**秒 格式的数据
     */
    public String minutConversion(BigDecimal minutes) {
//            int minutes = 1500;
//            int days = minutes / (24 * 60); // 计算天数
//            int hours = (minutes % (24 * 60)) / 60; // 计算小时数
//            int remainingMinutes = minutes % 60; // 计算剩余的分钟数
//            System.out.println(days + "天 " + hours + "小时 " + remainingMinutes + "分钟");

        //minutes 带小数的分钟数
        BigDecimal daysDecimal = minutes.divide(new BigDecimal("1440"), 0, BigDecimal.ROUND_DOWN); // 计算天数
        int days = daysDecimal.intValue();
        BigDecimal remainingMinutesDecimal = minutes.remainder(new BigDecimal("1440")); // 计算剩余分钟数

        BigDecimal hoursDecimal = remainingMinutesDecimal.divide(new BigDecimal("60"), 0, BigDecimal.ROUND_DOWN); // 计算小时数
        int hours = hoursDecimal.intValue();

        BigDecimal remainingMinutes = remainingMinutesDecimal.remainder(new BigDecimal("60")); // 计算剩余分钟数

        return days + "天" + hours + "小时" + remainingMinutes + "分钟";
    }

}
